package com.example.interview.ch01;

import lombok.Data;
import lombok.SneakyThrows;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;

/**
 * @author anin
 * @date 2022/3/21 9:42 PM
 */
public class Test {

    static List<Task> tasks = new ArrayList<>();

    @SneakyThrows
    public static void main(String[] args) {
        Task task1 = new Task("task1", 1, Result.SUCCESS);
        Task task2 = new Task("task2", 2, Result.SUCCESS);
        Task task3 = new Task("task3", 5, Result.FAIL);
        tasks.add(task1);
        tasks.add(task2);
        tasks.add(task3);

        for (Task task : tasks) {
            CompletableFuture.supplyAsync(() -> task.runTask())
                    .thenAccept((result -> callback(result, task)));
        }
        System.in.read();
    }

    public static void callback(Result result, Task task) {
        if (result == Result.FAIL) {
            for (Task callTask : tasks) {
                if (callTask != task) {
                    callTask.cancel();
                }
            }
        }
    }
}

@Data
class Task implements Callable<Result> {
    private String name;
    private Integer time;
    private Result result;

    public Task(String name, Integer time, Result result) {
        this.name = name;
        this.time = time;
        this.result = result;
    }

    boolean cancelling = false;
    volatile boolean cancelled = false;

    public Result runTask() {
        try {
            return this.call();
        } catch (Exception e) {
            return Result.FAIL;
        }
    }

    @SneakyThrows
    public void cancel() {
        cancelling = true;
        synchronized (this) {
            System.out.println(name + "任务回滚ing...");
            Thread.sleep(50);
            System.out.println(name + "任务回滚完成");
        }

        cancelled = true;


    }

    @SneakyThrows
    @Override
    public Result call() {
        int interval = 100;
        int total = 0;

        while (true){
            Thread.sleep(time);
            if(cancelling){
                continue;
            }
            total += interval;
            if (total >= time) {
                break;
            }
            if (cancelled) {
                return Result.CANCELLED;
            }
        }
        System.out.println(name + "任务执行，结果：" + result);
        return result;
    }
}

enum Result {
    SUCCESS,
    FAIL,
    CANCELLED
}